ARD2  RC2
Airbag Reference Demonstrator using MPC5604P
FLASH.c
Go to the documentation of this file.
00001 
00016 #include "Compile_Options.h"
00017 #include "derivative.h"
00018 #include "utils.h" /* For Copy Array */
00019 #include "flash.h"
00020 /*
00021  ******************************************************************************
00022  * constants
00023  ******************************************************************************
00024  */
00025  /*
00026  ******************************************************************************
00027  * Globals
00028  ******************************************************************************
00029  */
00030 /*
00031  ******************************************************************************
00032  * u8fnFlashWriteDataFromRAM
00033  ******************************************************************************
00034  */
00035 static uint8_t u8fnFlashWriteDataFromRAM(uint32_t* pu32AddressToWrite, \
00036                                          uint32_t* pu32ValueToWrite,   \
00037                                          Flash_t  ptFlashInstance,     \
00038                                          uint8_t  u8TwoContiguousWords)
00039 {
00040   uint8_t  u8Status;
00041   uint16_t u16TimeOut;
00042   
00043   u8Status = CLEAR;
00044   u16TimeOut = CLEAR;
00045   
00046   /* The first instruction selects the desired operation by setting its  */
00047   /* corresponding selection bit in MCR                                  */
00048   ptFlashInstance->MCR.B.PGM = TRUE;
00049   
00050   /* Next, write to the location so that the flash controller takes the  */
00051   /* values.                                                             */
00052   *pu32AddressToWrite = *pu32ValueToWrite;
00053   if(TRUE == u8TwoContiguousWords)
00054   {
00055     *(++pu32AddressToWrite) = *(++pu32ValueToWrite);
00056   }
00057   else
00058   {
00059     /* Nothing */
00060   }
00061   
00062   /* Set MCR[EHV] to 1 to start the internal program sequence */
00063   ptFlashInstance->MCR.B.EHV = TRUE;
00064   
00065   /* Wait for the programming to be done */
00066   do
00067   {
00068     u16TimeOut++;
00069   }while((CLEAR == ptFlashInstance->MCR.B.DONE) && \
00070          (FLASHING_TIMEOUT > u16TimeOut));
00071   
00072   if(FLASHING_TIMEOUT == u16TimeOut)
00073   {
00074     /* We timed-out. We need to flag this */
00075     u8Status = STATUS_FLASHING_TIME_OUT;
00076   }
00077   else
00078   {
00079     /* Nothing happened */
00080   }
00081   /* Confirm MCR[PEG] = 1. */
00082   if(TRUE != ptFlashInstance->MCR.B.PEG)
00083   {
00084     /* Set a flag */
00085     u8Status = STATUS_PROGRAMMED_WRONG;
00086   }
00087   else
00088   {
00089     /* We are happy */
00090   }
00091       
00092   /* Write a logic 0 to the MCR[EHV] bit. */
00093   ptFlashInstance->MCR.B.EHV = CLEAR;
00094   /* Write a logic 0 to the MCR[PGM] bit to terminate the program operation */
00095   ptFlashInstance->MCR.B.PGM = CLEAR;  
00096   
00097   return(u8Status);
00098 }
00099 /*
00100  ******************************************************************************
00101  * u8fnFlashEraseFromRAM
00102  ******************************************************************************
00103  */
00104 static uint8_t u8fnFlashEraseFromRAM(Flash_t ptFlashInstance, uint32_t u32LMS)
00105 {
00106   uint8_t  u8Status;
00107   uint32_t u32TimeOut;
00108   
00109   u8Status = CLEAR;
00110   u32TimeOut = CLEAR;
00111   
00112   /* 1. Change the value in the MCR[ERS] bit from 0 to 1. */
00113   ptFlashInstance->MCR.B.ERS = TRUE;
00114     
00115   /* According to the spec, start by selecting sectors that will be erased */
00116   ptFlashInstance->LMS.R = u32LMS;
00117     
00118   /* Write to any address in flash. This is referred to as an erase */
00119   /* interlock write.                                               */
00120   *(uint32_t*)DATA_FLASH_F3_SECTOR_MIN = CLEAR;
00121   *(uint32_t*)CODE_FLASH_F3_SECTOR_MIN = CLEAR;
00122   
00123   /* Set MCR[EHV] to start the internal erase sequence */
00124   ptFlashInstance->MCR.B.EHV = TRUE;
00125   
00126   u32TimeOut = CLEAR;
00127   /* Wait for the operation to be done */
00128   do
00129   {
00130     u32TimeOut++;
00131   }while((CLEAR == ptFlashInstance->MCR.B.DONE) && \
00132          (ERASING_TIMEOUT > u32TimeOut));
00133   
00134   if(ERASING_TIMEOUT == u32TimeOut)
00135   {
00136     /* We timed-out. We need to flag this */
00137     u8Status = STATUS_FLASHING_TIME_OUT;
00138   }
00139   else
00140   {
00141     /* Nothing happened */
00142   }
00143   
00144   /* Confirm MCR[PEG] = 1. */
00145   if(TRUE != ptFlashInstance->MCR.B.PEG)
00146   {
00147     /* Set a flag */
00148     u8Status = STATUS_PROGRAMMED_WRONG;
00149   }
00150   else
00151   {
00152     /* We are happy */
00153   }
00154    /* Write a logic 0 to the MCR[EHV] bit. */
00155   ptFlashInstance->MCR.B.EHV = CLEAR;
00156 
00157   /* Write a logic 0 to the MCR[ERS] bit to terminate the program operation */
00158   ptFlashInstance->MCR.B.ERS = CLEAR;  
00159   
00160   return(u8Status);
00161 }
00162 /*
00163  ******************************************************************************
00164  * vfnFlashArray
00165  ******************************************************************************
00166  */
00167 uint8_t u8fnFlashWrite(uint32_t* pu32Source, uint32_t* pu32Destination, \
00168                        uint16_t u16Size)
00169 {
00170   Flash_t ptFlashInstance;
00171   uint8_t u8Status;
00172   uint8_t u8Sector;
00173   uint8_t u8TwoBytesAtOnce;
00174   
00175   /* Init local variables and select flash instance */
00176   u8Status = CLEAR;
00177   u8Sector = CLEAR;
00178   u8TwoBytesAtOnce = CLEAR;
00179   ptFlashInstance = tfnFlashSelectInstance(\
00180                                u8fnReturnTypeOfFlash(\
00181                                       (uint32_t)(pu32Destination + u16Size)));
00182   /* If we still have a valid instance */
00183   if(CLEAR != ptFlashInstance)
00184   {
00185     /* Clear the lock - this is a write-once per reset operation.         */
00186     /* In the spec, p. 379, 382, passwords are defined for editing LML    */
00187     /* and SLL. These are written here first.                             */
00188     ptFlashInstance->LML.R = FLASH_PRIMARY_LOCK_KEY;
00189     ptFlashInstance->LML.R = FLASH_ALLOW_COMPLETE_REFLASH;
00190     ptFlashInstance->SLL.R = FLASH_SECONDARY_LOCK_KEY;
00191     ptFlashInstance->SLL.R = FLASH_ALLOW_COMPLETE_REFLASH;
00192     
00193     /* Copy the flashing routine to RAM from where we will execute */
00194     vfnCopyArray((uint8_t*)&u8fnFlashWriteDataFromRAM, \
00195                  (uint8_t*)RAM_ADDRESS_FOR_FLASHING_ROUTINE,
00196                  FLASH_ROUTINE_SIZE);
00197   
00198     for(; u16Size > CLEAR; u16Size--)
00199     {
00200       if(NOT_FLASHABLE != u8Sector)
00201       {
00202         /* If we can flash, let's see if we're writing one or two words at */
00203         /* the same time. This is a hardware capability.                   */
00204         if(1u < u16Size)
00205         {
00206           /* If BIT3 is clear we know that the destination address will is */
00207           /* at the start of a 64-bit register, and therefore we can flash */
00208           /* two 32-bit words at once.                                     */
00209           if((uint32_t)pu32Destination & BIT3)
00210           {
00211             u8TwoBytesAtOnce = CLEAR;
00212           }
00213           else
00214           {
00215             u8TwoBytesAtOnce = TRUE;
00216           }
00217         }
00218         else
00219         {
00220           u8TwoBytesAtOnce = CLEAR;
00221         }
00222       
00223         /* Now, let's actually program by jumping into RAM. */
00224         u8Status |= PROGRAM(pu32Destination, pu32Source, ptFlashInstance, u8TwoBytesAtOnce);
00225       } /* end if */
00226       else
00227       {
00228         u8Status = u8Sector;
00229       }
00230     
00231       /* Let's Increment our pointers coherently with how many values were */
00232       /* flashed                                                           */
00233       pu32Destination += (1 + u8TwoBytesAtOnce);
00234       pu32Source += (1 + u8TwoBytesAtOnce);
00235     
00236       /* Also, don't forget to decrement size manually if two words were   */
00237       /* flashed.                                                          */
00238       u16Size -= u8TwoBytesAtOnce;
00239     
00240     }/* End For */
00241   } /* end if memory locations are valid */
00242   else
00243   {
00244     u8Status = NOT_FLASHABLE;
00245   }
00246   return(u8Status);
00247 }
00248 /*
00249  ******************************************************************************
00250  * u8fnFlashErase
00251  ******************************************************************************
00252  */
00253 uint8_t u8fnFlashErase(uint32_t* pu32DataToErase)
00254 {
00255   uint8_t  u8Status;
00256   uint8_t  u8TypeOfFlash;
00257   uint8_t  u8FlashSector;
00258   uint32_t u32LMS;
00259   Flash_t  ptMyFlash;
00260   
00261   /* Init locals */
00262   u8Status = CLEAR;
00263   u8FlashSector = CLEAR;
00264   u32LMS = CLEAR;
00265   
00266   /* Figure out what module we will be erasing */
00267   u8TypeOfFlash = u8fnReturnTypeOfFlash((uint32_t)pu32DataToErase);
00268   
00269   if(DATA_FLASH == u8TypeOfFlash)
00270   {
00271     /* Define instance as Data flash. */
00272     ptMyFlash = (Flash_t)&DFLASH;
00273     u8FlashSector = u8fnReturnDataFlashSector((uint32_t)pu32DataToErase);
00274   }
00275   else if(CODE_FLASH == u8TypeOfFlash)
00276   {
00277     /* Define instance as Code  flash. */
00278     ptMyFlash = &CFLASH;
00279     u8FlashSector = u8fnReturnCodeFlashSector((uint32_t)pu32DataToErase);
00280   }
00281   else
00282   {
00283     u8Status = NOT_FLASHABLE;
00284   }
00285   
00286   if(CLEAR == u8Status)
00287   {
00288     if(NOT_FLASHABLE != u8FlashSector)
00289     {
00290       /* Clear the lock - this is a write-once per reset operation.         */
00291       /* In the spec, p. 379, 382, passwords are defined for editing LML    */
00292       /* and SLL. These are written here first.                             */
00293       ptMyFlash->LML.R = FLASH_PRIMARY_LOCK_KEY;
00294       ptMyFlash->LML.R = FLASH_ALLOW_COMPLETE_REFLASH;
00295       ptMyFlash->SLL.R = FLASH_SECONDARY_LOCK_KEY;
00296       ptMyFlash->SLL.R = FLASH_ALLOW_COMPLETE_REFLASH;
00297       
00298       /* Copy the erase routine to RAM from where we will execute */
00299       vfnCopyArray((uint8_t*)&u8fnFlashEraseFromRAM, \
00300                    (uint8_t*)RAM_ADDRESS_FOR_FLASHING_ROUTINE,
00301                    ERASE_ROUTINE_SIZE);
00302       /* Figure out what LMS bits will be set - this is directly mapped */
00303       /* to Hardware.                                                   */
00304       u32LMS = u32fnFlashSectorToLMS(u8FlashSector);
00305       
00306       /* Now ERASE!! */
00307       u8Status = ERASE(ptMyFlash, u32LMS);
00308           
00309     }
00310     else
00311     {
00312       u8Status = NOT_FLASHABLE;
00313     }
00314   }
00315   else
00316   {
00317     /* Already flagged - exit */
00318   }
00319   
00320   return(u8Status);
00321 }
00322 /*
00323  ******************************************************************************
00324  * u8fnReturnTypeOfFlash
00325  ******************************************************************************
00326  */
00327 static uint8_t u8fnReturnTypeOfFlash(uint32_t u32Location)
00328 {
00329   uint8_t u8Status;
00330   
00331   u8Status = CLEAR;
00332   
00333   if((CODE_FLASH_ARRAY_0_TOP_ADDRESS >= u32Location) && \
00334      (CODE_FLASH_ARRAY_0_MIN_ADDRESS <= u32Location))
00335   {
00336     u8Status = CODE_FLASH;
00337   }
00338   else if((CODE_FLASH_ARRAY_0_SHADOW_TOP_ADDRESS >= u32Location) && \
00339           (CODE_FLASH_ARRAY_0_SHADOW_MIN_ADDRESS <= u32Location))
00340   {
00341     u8Status = CODE_FLASH_SHADOW;
00342   }
00343   else if((DATA_FLASH_ARRAY_0_TOP_ADDRESS >= u32Location) && \
00344           (DATA_FLASH_ARRAY_0_MIN_ADDRESS <= u32Location))
00345   {
00346     u8Status = DATA_FLASH;
00347   }
00348   else
00349   {
00350     u8Status = NOT_FLASHABLE;
00351   }
00352   
00353   return(u8Status);
00354 }
00355 /*
00356  ******************************************************************************
00357  * tfnFlashSelectInstance
00358  ******************************************************************************
00359  */
00360 static Flash_t tfnFlashSelectInstance(uint8_t u8Instance)
00361 {
00362   Flash_t ptFlashInstance;
00363   if(CODE_FLASH == u8Instance)
00364   {
00365     ptFlashInstance = &CFLASH;
00366   }
00367   else if(DATA_FLASH == u8Instance)
00368   {
00369     ptFlashInstance = (Flash_t)&DFLASH;
00370   }
00371   else
00372   {
00373     ptFlashInstance = CLEAR;
00374   }
00375   
00376   return(ptFlashInstance);
00377 }
00378 /*
00379  ******************************************************************************
00380  * u8fnFlashReadBackInstance
00381  ******************************************************************************
00382  */
00383 static uint8_t u8fnFlashReadBackInstance(Flash_t ptFlashInstance)
00384 {
00385   uint8_t u8FlashInstance;
00386   if(ptFlashInstance == &CFLASH)
00387   {
00388     u8FlashInstance = CODE_FLASH;
00389   }
00390   else if(ptFlashInstance == (Flash_t)&DFLASH)
00391   {
00392     u8FlashInstance = DATA_FLASH;
00393   }
00394   else
00395   {
00396     u8FlashInstance = NOT_FLASHABLE;
00397   }
00398   
00399   return(u8FlashInstance);
00400 }
00401 /*
00402  ******************************************************************************
00403  * u8fnReturnCodeFlashSector
00404  ******************************************************************************
00405  */
00406 static uint8_t u8fnReturnCodeFlashSector(uint32_t u32Address)
00407 {
00408   uint8_t u8Status;
00409     
00410   u8Status = CLEAR;
00411   
00412   /* This should only be true if the passed address is in the valid region */
00413   if(CODE_FLASH_ARRAY_0_TOP_ADDRESS >= u32Address)
00414   {
00415     if(CODE_FLASH_F1_SECTOR_MIN > u32Address)
00416     {
00417       u8Status = F0;
00418     }
00419     else if(CODE_FLASH_F2_SECTOR_MIN > u32Address)
00420     {
00421       u8Status = F1;
00422     }
00423     else if(CODE_FLASH_F3_SECTOR_MIN > u32Address)
00424     {
00425       u8Status = F2;
00426     }
00427     else if(CODE_FLASH_F4_SECTOR_MIN > u32Address)
00428     {
00429       u8Status = F3;
00430     }
00431     else if(CODE_FLASH_F5_SECTOR_MIN > u32Address)
00432     {
00433       u8Status = F4;
00434     }
00435     else if(CODE_FLASH_F6_SECTOR_MIN > u32Address)
00436     {
00437       u8Status = F5;
00438     }
00439     else if(CODE_FLASH_F7_SECTOR_MIN > u32Address)
00440     {
00441       u8Status = F6;
00442     }
00443     else if(CODE_FLASH_F7_SECTOR_MAX >= u32Address)
00444     {
00445       u8Status = F7;
00446     }
00447     else
00448     {
00449       u8Status = NOT_FLASHABLE;
00450     }
00451   }
00452   else
00453   {
00454     u8Status = NOT_FLASHABLE;
00455   }
00456   
00457   return(u8Status);
00458 }
00459 /*
00460  ******************************************************************************
00461  * u8fnReturnTypeOfFlash
00462  ******************************************************************************
00463  */
00464 static uint8_t u8fnReturnDataFlashSector(uint32_t u32Address)
00465 {
00466   uint8_t u8Status;
00467     
00468   u8Status = CLEAR;
00469   
00470   /* This should only be true if the passed address is in the valid region */
00471   if(DATA_FLASH_F0_SECTOR_MIN <= u32Address)
00472   {
00473     u32Address -= DATA_FLASH_F0_SECTOR_MIN;
00474     u8Status = (uint8_t)(u32Address / DATA_FLASH_SECTOR_SIZE);
00475   }
00476   else
00477   {
00478     u8Status = NOT_FLASHABLE;
00479   }
00480   
00481   return(u8Status);
00482 }
00483 /*
00484  ******************************************************************************
00485  * u8fnFlashSectorToLMS
00486  ******************************************************************************
00487  */
00488 static uint32_t u32fnFlashSectorToLMS(uint8_t u8Sector)
00489 {
00490   uint32_t u32LMS;
00491   
00492   u32LMS = CLEAR;
00493   
00494   /* Start with Mid address spaces */
00495   if(F6 <= u8Sector)
00496   {
00497     /* Set the corresponding bits for MSL within LMS - Bits 14 + 15 according */
00498     /* to spec.                                                               */
00499     u32LMS = (1u << ((u8Sector - F6) + BITS_IN_16)); 
00500   }
00501   else
00502   {
00503     u32LMS = (1u << u8Sector);
00504   }
00505   
00506   return(u32LMS);
00507 }
00508 /*
00509  ******************************************************************************
00510  *
00511  *  End of file.
00512  *
00513  ******************************************************************************
00514  */